package net.pimpas.web.jsf.util;

import java.util.ArrayList;
import java.util.List;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import net.pimpas.logging.serviceprovider.LoggingServiceProvider;
import net.pimpas.logging.serviceprovider.LoggingServiceProviderFactoryImpl;
import net.pimpas.util.reflection.ReflectionUtil;

public abstract class ComponentUtils {
	
	public static final int			SERVER_ID		= 0;
	public static final int			CLIENT_ID		= 1;
	
	private static final LoggingServiceProvider logger = 
		LoggingServiceProviderFactoryImpl.getLoggingServiceProvider(ComponentUtils.class);
	
	public static boolean isCorrectComponentType(UIComponent component, Class clazz) {
		return (ReflectionUtil.isSubclass(component.getClass(), clazz));
	}
	
	public static UIComponent findMyParentComponent(UIComponent component, Class parentClass) {
		if(ReflectionUtil.isSubclass(component.getClass(), parentClass)) return component;
		while(component != null && !ReflectionUtil.isSubclass(component.getClass(), parentClass))
			component = component.getParent();
		
		return component;
	}
	
	public static UIComponent getComponentById(UIComponent component, FacesContext context, String componentId, int type) {
		if(component.getId() != null)
			switch(type) {
				case ComponentUtils.SERVER_ID:
					if(component.getId().equals(componentId))
						return component;
					break;
				case ComponentUtils.CLIENT_ID:
					if(component.getClientId(context).equals(componentId))
						return component;
					break;
			}
		
		if(component.getChildCount() > 0) {
			UIComponent cp = null;
			for(int i=0;i<component.getChildCount();i++) {
				cp = ComponentUtils.getComponentById((UIComponent) component.getChildren().get(i), context, componentId, type);
				if(cp != null) return cp;
			}
		}
		return null;
	}
	
	public static Boolean havComponentAsChild(UIComponent cp, Class child) {
		List t = getAllComponentsByClass(cp, child);
		
		return t.size()>0;
	}
	
	public static <T extends UIComponent>List<T> getAllComponentsByClass(UIComponent cp, Class c) {
		List<T> l = new ArrayList<T>();
		getComponents(l, cp, c);
		
		return l;
	}
	
	public static <T extends UIComponent>T getComponentByClass(UIComponent cp, Class c) {
		List<T> t = ComponentUtils.getAllComponentsByClass(cp, c);
		return (t.size()==0) ? null : t.get(0);
	}
	
	@SuppressWarnings("unchecked")
	private static <T extends UIComponent>void getComponents(List<T> t, UIComponent cp, Class c) {
		if(cp.getChildCount() > 0)
			for(int i=0;i<cp.getChildCount();i++) {
				ComponentUtils.getComponents(t, (UIComponent) cp.getChildren().get(i), c);
			}
		if(ReflectionUtil.isSubclass(cp.getClass(), c))
			t.add((T) cp);
	}
	
	public static Boolean isOnlyValueBinding(String value) {
		if(value == null || "".equals(value)) return Boolean.FALSE;
		
		if(value.startsWith("#{") && value.endsWith("}"))
			return (value.indexOf("#{") == value.lastIndexOf("#{") &&
					value.indexOf("}") == value.lastIndexOf("}"));
		
		return Boolean.FALSE;
	}
	
	public static Boolean containsValueBinding(String value) {
		if(value.indexOf("#{")>=0 && value.indexOf("}")>=0 &&
				value.indexOf("#{") < value.indexOf("}"))
			return Boolean.TRUE;
		return Boolean.FALSE;
	}
	
	public static String getValueBinding(String value) {
		if(!containsValueBinding(value)) return null;
		int posI = value.indexOf("#{");
		int posF = value.indexOf("}");
		
		return value.substring(posI, posF+1);
	}
}